package com.goodmr.passport.webapp.exception;

import com.goodmr.passport.webapp.enums.ErrorEnum;
import com.goodmr.passport.webapp.model.ErrorResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import java.util.List;
import java.util.Locale;

/**
 * 全局异常处理
 *
 * @author <a href="mailto:bingdong13@msn.com">bigo</a>
 */
@ControllerAdvice
@ResponseBody
@Slf4j
public class AppExceptionHandler {

    private final MessageSource messageSource;

    @Autowired
    public AppExceptionHandler(MessageSource messageSource) {
        this.messageSource = messageSource;
    }

    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ErrorResult exceptionHandler(Exception e) {

        ErrorEnum error = ErrorEnum.INTERNAL_SERVER_ERROR;
        String message = getLocaleMessage(error.getResource(), error.getArgs());

        log.error(message, e);

        return new ErrorResult(error.getCode(), message);
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
    public ErrorResult argumentNotValidHandler(MethodArgumentNotValidException e) {

        ErrorEnum error = ErrorEnum.REQUEST_PARAM_ERROR;
        String message = getLocaleMessage(error.getResource(), error.getArgs());

        log.error(message, e);

        return new ErrorResult(error.getCode(), message);
    }

    @ExceptionHandler(BadRequestException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ErrorResult BadRequestHandler(BadRequestException e) {

        ErrorEnum error = e.getError();
        String message = getLocaleMessage(error.getResource(), error.getArgs());

        log.error(message, e);

        return new ErrorResult(error.getCode(), message);
    }

    @ExceptionHandler(UnauthorizedException.class)
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public ErrorResult UnauthorizedHandler(UnauthorizedException e) {

        ErrorEnum error = e.getError();
        String message = getLocaleMessage(error.getResource(), error.getArgs());

        log.error(message, e);

        return new ErrorResult(error.getCode(), message);
    }

    /**
     * 获取本地语言格式化资源
     *
     * @param resource 资源标识
     * @return 资源信息
     */
    private String getLocaleMessage(String resource, List<Object> args) {

        Locale locale = LocaleContextHolder.getLocale();

        return messageSource.getMessage(resource, args.toArray(), locale);
    }
}
